package com.yaofeng.mybatis.modules.sys.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yaofeng.mybatis.common.ErrorCodeEnum;
import com.yaofeng.mybatis.exception.BusinessException;
import com.yaofeng.mybatis.modules.sys.entity.*;
import com.yaofeng.mybatis.modules.sys.mapper.*;
import com.yaofeng.mybatis.modules.sys.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yaofeng.mybatis.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yaofeng
 * @since 2019-08-30
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserTokenMapper userTokenMapper;

    @Resource
    private UserPostMapper  userPostMapper;

    @Resource
    private UserRoleMapper  userRoleMapper;

    @Resource
    private RoleMapper  roleMapper;

    @Override
    public Object login(String loginName, String userPassword) throws Exception {

        // 验证账号
        User user = userMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getLoginName, loginName));
        if (user == null) {
            throw new BusinessException(ErrorCodeEnum.LOGIN_NAME__ERROR.getErrMsg());
        }

        // 获取盐值
        String salt = user.getSalt();

        // 验证密码
        user = userMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getLoginName, loginName).eq(User::getUserPassword, Sha256Util.encoder(userPassword, salt)));
        if (user == null) {
            throw new BusinessException(ErrorCodeEnum.USER_PASSWORD_ERROR.getErrMsg());
        }
        String token = JWTUtil.sign(loginName, Sha256Util.encoder(userPassword, salt));
        JSONObject object = new JSONObject();
        object.put("token", token);
        object.put("userId", user.getUserId().toString());
        object.put("userName", user.getUserName());

        return object;
    }


    @Override
    public void logOut() {
        String token   = SecurityUtils.getSubject().getPrincipal().toString();
        Date expiredTime  = JWTUtil.getExpiresDate(token);
        UserToken   userToken  = UserToken.builder().tokenValue(token)
                .expiredTime(expiredTime).build();
        // 作废ip入库
        userTokenMapper.insert(userToken);
        SecurityUtils.getSubject().logout();
        // 清理所有缓存数据
    }

    @Override
    @Transactional()
    public void saveUser(User user) {
        // 查询账号是否已经存在
        User exist = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getLoginName,user.getLoginName()));
        if(exist!=null){
           throw   new BusinessException(ErrorCodeEnum.LOGIN_NAME__EXIST);
        }
        // 判断手机号是否存在
        exist = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getMobile,user.getMobile()));
        if(exist!=null){
            throw   new BusinessException(ErrorCodeEnum.LOGIN_PHONE__EXIST);
        }
        // 判断邮箱是否存在
        if(StringUtils.isNotEmpty(user.getEmail())){
            exist = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getEmail,user.getEmail()));
            if(exist!=null){
                throw   new BusinessException(ErrorCodeEnum.LOGIN_EMAIN__EXIST);
            }
        }
        /**
         *  处理密码和盐值
         */
        // 获取随机salt
        String salt = SaltUtil.salt();
        // 密码加密 新增用户默认6个0
        String userPassword = Sha256Util.encoder(Constants.DEFAULT_USER_PASSWORD, salt);
        user.setSalt(salt);
        user.setUserPassword(userPassword);
        userMapper.insert(user);
        // 插如用户与岗位相关信息
        insertUserPost(user);
        // 插入用户与角色相关信息
        insertUserRole(user);
    }

    @Override
    public IPage<User> selectPage(Page<User> page, Map<String, Object> params) {
        return userMapper.selectUserPage(page,params);
    }

    @Override
    @Transactional()
    public void updateUser(User user) {
        userMapper.updateById(user);
        // 删除用户相关的岗位信息
        deleteUserPost(user);
        // 删除用户角色相关的信息
        deleteUserRole(user);
        // 插如用户与岗位相关信息
        insertUserPost(user);
        // 插入用户与角色相关信息
        insertUserRole(user);
    }

    @Override
    public void deleteUser(Long id) {
        // 判断是否有管理员角色 有提示是管理员不能删除
        if(hasAdminRole(id)){
            throw new BusinessException(ErrorCodeEnum.ADMIN_ROLE_NOT_DELETE);
        }
        // 删除用户相关的岗位信息
        deleteUserPost(User.builder().userId(id).build());
        // 删除用户角色相关的信息
        deleteUserRole(User.builder().userId(id).build());
        // 删除用户
        userMapper.deleteById(id);
    }

    /**
     * 用户是否有管理员角色
     * @param id
     * @return
     */
    private boolean hasAdminRole(Long id) {
        AtomicBoolean hasAdminRole = new AtomicBoolean(false);
        List<UserRole>  userRoles  = userRoleMapper.selectList(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId,id));
        List<Long> roleIdList = userRoles.stream().map(u -> u.getRoleId()).collect(Collectors.toList());
        List<Role>  roles  = roleMapper.selectBatchIds(roleIdList);
        roles.forEach(r->{
            if(r.getRoleName().contains("系统管理员")){
                hasAdminRole.set(true);
            }
        });
        return hasAdminRole.get();
    }

    /**
     *   删除用户相关的岗位信息
     * @param user
     */
    private void deleteUserPost(User user) {
        userPostMapper.delete(Wrappers.<UserPost>lambdaQuery().eq(UserPost::getUserId,user.getUserId()));
    }


    /**
     *  删除用户角色相关的信息
     * @param user
     */
    private void deleteUserRole(User user) {
        userRoleMapper.delete(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId,user.getUserId()));
    }

    /**
     *  插如用户与岗位相关信息
     * @param user
     */
    private void insertUserPost(User user) {
        String[] postIds  =  user.getPostIds();
        List<UserPost> userPosts ;
        if(postIds!=null&&postIds.length>0){
            userPosts = new ArrayList<>();
            for(String id:postIds){
               UserPost  userPost  = new UserPost();
                userPost.setPostId(Long.valueOf(id));
                userPost.setUserId(user.getUserId());
                userPosts.add(userPost);
            }
            userPosts.forEach(u-> userPostMapper.insert(u));
        }

    }

    /**
     *  插入用户与角色相关信息
     * @param user
     */
    private void insertUserRole(User user) {
        String[] roleIds  =  user.getRoleIds();
        List<UserRole> userRoles ;
        if(roleIds!=null&&roleIds.length>0){
            userRoles = new ArrayList<>();
            for(String id:roleIds){
                UserRole  userRole  = new UserRole();
                userRole.setRoleId(Long.valueOf(id));
                userRole.setUserId(user.getUserId());
                userRoles.add(userRole);
            }
            userRoles.forEach(u-> userRoleMapper.insert(u));
        }
    }
}
